<template>
  <div class="error-boundary">
    <div v-if="hasError" class="error-fallback">
      <div class="error-container">
        <div class="error-icon">⚠️</div>
        <h2 class="error-title">{{ errorTitle }}</h2>
        <p class="error-message">{{ errorMessage }}</p>
        <div class="error-details" v-if="showDetails">
          <details>
            <summary>错误详情</summary>
            <pre class="error-stack">{{ errorInfo.stack }}</pre>
          </details>
        </div>
        <div class="error-actions">
          <button @click="retry" class="retry-btn">重试</button>
        </div>
      </div>
    </div>
    <slot v-else />
  </div>
</template>

<script setup lang="ts">
import { ref, onErrorCaptured, defineProps, defineEmits } from 'vue'
import * as Sentry from '@sentry/vue'

interface ErrorInfo {
  message: string
  stack?: string
  componentStack?: string
  errorBoundary?: string
}

interface Props {
  fallbackComponent?: string
  errorTitle?: string
  errorMessage?: string
  showDetails?: boolean
  onError?: (error: Error, errorInfo: ErrorInfo) => void
}

const props = withDefaults(defineProps<Props>(), {
  errorTitle: '出现了一个错误',
  errorMessage: '很抱歉，页面遇到了问题。我们已经记录了这个错误。',
  showDetails: true
})

const emit = defineEmits<{
  error: [error: Error, errorInfo: ErrorInfo]
  retry: []
}>()

const hasError = ref(false)
const errorInfo = ref<ErrorInfo>({
  message: '',
  stack: ''
})

// 捕获子组件错误
onErrorCaptured((error: Error, instance, info) => {
  console.error('ErrorBoundary caught an error:', error)
  
  hasError.value = true
  errorInfo.value = {
    message: error.message,
    stack: error.stack,
    componentStack: info,
    errorBoundary: 'ErrorBoundary'
  }

  // 上报错误到 Sentry（仅在启用时）
  const enableSentry = import.meta.env.VITE_ENABLE_SENTRY === 'true' || import.meta.env.PROD
  
  if (enableSentry) {
    Sentry.withScope((scope) => {
      scope.setTag('errorBoundary', true)
      scope.setLevel('error')
      scope.setContext('errorInfo', {
        componentStack: info,
        errorBoundary: 'ErrorBoundary',
        componentName: (instance as any)?.$?.type?.name || instance?.constructor?.name || 'Unknown'
      })
      Sentry.captureException(error)
    })
  } else {
    console.log('Development mode: Error would be sent to Sentry in production:', error)
  }

  // 触发错误事件
  emit('error', error, errorInfo.value)
  
  // 调用外部错误处理函数
  if (props.onError) {
    props.onError(error, errorInfo.value)
  }

  // 阻止错误继续向上传播
  return false
})

// 重试功能
const retry = () => {
  hasError.value = false
  errorInfo.value = {
    message: '',
    stack: ''
  }
  emit('retry')
}

// 报告错误功能
const reportError = () => {
  const enableSentry = import.meta.env.VITE_ENABLE_SENTRY === 'true' || import.meta.env.PROD
  
  if (enableSentry) {
    // 生产环境或启用 Sentry 时使用反馈对话框
    Sentry.showReportDialog({
      title: '报告错误',
      subtitle: '如果您愿意，请告诉我们发生了什么',
      subtitle2: '我们的团队会及时查看并修复问题',
      labelName: '姓名',
      labelEmail: '邮箱',
      labelComments: '详细描述',
      labelClose: '关闭',
      labelSubmit: '提交',
      errorGeneric: '提交时发生未知错误，请稍后再试',
      errorFormEntry: '部分字段无效，请检查后重试',
      successMessage: '反馈已发送，感谢您的报告！'
    })
  } else {
    // 开发环境中显示简单的提示
    alert('开发环境：错误反馈功能在生产环境中可用')
  }
}
</script>

<style scoped>
.error-boundary {
  width: 100%;
  height: 100%;
}

.error-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 300px;
  padding: 20px;
}

.error-container {
  max-width: 500px;
  text-align: center;
  padding: 30px;
  border: 1px solid #f5c6cb;
  border-radius: 8px;
  background-color: #f8d7da;
  color: #721c24;
}

.error-icon {
  font-size: 3rem;
  margin-bottom: 16px;
}

.error-title {
  font-size: 1.5rem;
  font-weight: 600;
  margin-bottom: 12px;
  color: #721c24;
}

.error-message {
  margin-bottom: 20px;
  line-height: 1.5;
  color: #856404;
}

.error-details {
  margin-bottom: 20px;
  text-align: left;
}

.error-details summary {
  cursor: pointer;
  font-weight: 500;
  margin-bottom: 8px;
  color: #721c24;
}

.error-stack {
  background-color: #f1f3f4;
  padding: 12px;
  border-radius: 4px;
  font-size: 0.875rem;
  overflow-x: auto;
  max-height: 200px;
  color: #333;
}

.error-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
}

.retry-btn,
.report-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-weight: 500;
  transition: background-color 0.2s;
}

.retry-btn {
  background-color: #007bff;
  color: white;
}

.retry-btn:hover {
  background-color: #0056b3;
}

.report-btn {
  background-color: #6c757d;
  color: white;
}

.report-btn:hover {
  background-color: #545b62;
}
</style>